home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 2: Applications / Linux Cubed Series 2 - Applications.iso / circuits / irsim-ca.2 / irsim-ca / irsim-cap-9.2 / src / irsim / genspktbl.c < prev    next >
C/C++ Source or Header  |  1993-01-15  |  10KB  |  355 lines

  1. /* 
  2.  *     ********************************************************************* 
  3.  *     * Copyright (C) 1988, 1990 Stanford University.                     * 
  4.  *     * Permission to use, copy, modify, and distribute this              * 
  5.  *     * software and its documentation for any purpose and without        * 
  6.  *     * fee is hereby granted, provided that the above copyright          * 
  7.  *     * notice appear in all copies.  Stanford University                 * 
  8.  *     * makes no representations about the suitability of this            * 
  9.  *     * software for any purpose.  It is provided "as is" without         * 
  10.  *     * express or implied warranty.  Export of this software outside     * 
  11.  *     * of the United States of America may require an export license.    * 
  12.  *     ********************************************************************* 
  13.  */
  14.  
  15. /*
  16.  * Program to generate the spike fluctuation and delay lookup tables.
  17.  */
  18.  
  19.  
  20. #include <stdio.h>
  21. #include <math.h>
  22.  
  23. extern    void    exit();
  24.  
  25.     /* forward references */
  26. void    BuildTables(), PrintTable(), linear_spike(), rk4_error();
  27. void    nldh_vector(), nldl_vector();
  28. double    nldh_rk4(), nldl_rk4();
  29.  
  30.  
  31. #define SPIKETBLSIZE    10
  32. #define STEP        (1.0 / SPIKETBLSIZE)       /* Step of computation */
  33.  
  34. #define    NLSPKMIN    0
  35. #define    NLSPKMAX    1
  36. #define    LINEARSPK    2
  37.  
  38.  
  39. double    nldltab[ SPIKETBLSIZE + 1 ][ SPIKETBLSIZE + 1 ];
  40. double    nldhtab[ SPIKETBLSIZE + 1 ][ SPIKETBLSIZE + 1 ];
  41. double    linrtab[ SPIKETBLSIZE + 1 ][ SPIKETBLSIZE + 1 ];
  42. double    delaytab[ SPIKETBLSIZE + 1 ][ SPIKETBLSIZE + 1 ];
  43.  
  44.  
  45. #define    SMALL    0.01
  46. #define    LARGE    0.99
  47.  
  48.  
  49. FILE    *F;
  50.  
  51.  
  52. main( argc, argv )
  53.   int   argc;
  54.   char  *argv[];
  55.   {
  56.     char  *fname;
  57.     char  *size = "SPIKETBLSIZE";
  58.  
  59.     if( argc == 1 )
  60.     fname = "spiketbl.c";
  61.     else if( argc == 2 )
  62.     fname = argv[1];
  63.     else
  64.     fprintf( stderr, "Usage: genspktbl [filename]\n" ), exit( 1 );
  65.  
  66.     if( (F = fopen( fname, "w" )) == NULL )
  67.     fprintf( stderr, "can not open `%s'\n", fname ), exit( 1 );
  68.  
  69.     BuildTables();
  70.  
  71.     fprintf( F, "/* DO NOT EDIT. THIS FILE IS GENERATED BY genspktbl */\n\n" );
  72.     fprintf( F, "#define SPIKETBLSIZE    %d\n\n", SPIKETBLSIZE );
  73.     fprintf( F, "#define NLSPKMIN        %d\n", NLSPKMIN );
  74.     fprintf( F, "#define NLSPKMAX        %d\n", NLSPKMAX );
  75.     fprintf( F, "#define LINEARSPK       %d\n", LINEARSPK );
  76.     fprintf( F, "\n" );
  77.  
  78.     fprintf( F, "static float spikeTable[ 3 ][ %s + 1 ][ %s + 1 ] =\n{\n",
  79.       size, size );
  80.     fprintf( F, "\t/* non-linear nmos driven low / pmos driven high */\n" );
  81.     PrintTable( nldltab, "%.3f" );
  82.     fprintf( F, "\n\t/* non-linear nmos driven high / pmos driven low */\n" );
  83.     PrintTable( nldhtab, "%.3f" );
  84.     fprintf( F, "\n\t/* linear RC (nmos-pmos mix)*/\n" );
  85.     PrintTable( linrtab, "%.3f" );
  86.     fprintf( F, "};\n\n" );
  87.  
  88.     fprintf( F, "static float delayTable[ %s + 1 ][ %s + 1 ] = \n{\n",
  89.       size, size );
  90.     PrintTable( delaytab, "%.5e" );
  91.     fprintf( F, "};\n" );
  92.  
  93.     exit( 0 );
  94.     /* NOTREACHED */
  95.   }
  96.  
  97.  
  98. void PrintTable( tab, fmt )
  99.   double  tab[ SPIKETBLSIZE+1 ][ SPIKETBLSIZE+1 ];
  100.   char    *fmt;
  101.   {
  102.     register  int  alpha, beta;
  103.  
  104.     for( beta = 0; beta <= SPIKETBLSIZE; beta++ )
  105.       {
  106.     if( beta == 0 )
  107.         fprintf( F, "/* .01 */" );
  108.     else if( beta == SPIKETBLSIZE )
  109.         fprintf( F, "/* .99 */" );
  110.     else
  111.         fprintf( F, "/* 0.%d */", beta );
  112.  
  113.     for( alpha = 0; alpha <= SPIKETBLSIZE; alpha++ )
  114.       {
  115.         fprintf( F, "  " );
  116.         fprintf( F, fmt, tab[ beta ][ alpha ] );
  117.         fprintf( F, "," );
  118.         if( (alpha + 1) % 4 == 0 )
  119.         fprintf( F, "\n         " );
  120.       }
  121.     fprintf( F, "\n" );
  122.       }
  123.   }
  124.  
  125.  
  126.  
  127. /* 
  128.  * Peak voltage for a 2-transistors-2-capacitors network, as a function
  129.  * of alpha and beta.  Compute spikes for nmos network driven to Gnd and
  130.  * to Vdd, placing the results in nldltab and nldhtab respectively.
  131.  *
  132.  * Alpha is the ratio of resistance of the resistor closer to the driver to 
  133.  * the total resistance.
  134.  * Beta is the ratio of capacitance of the capacitor closer to the driver to 
  135.  * the total capacitance.
  136.  *
  137.  */
  138. void BuildTables()
  139.   {   
  140.     double        alpha, beta, step;
  141.     register int  i, j;
  142.  
  143.  
  144.     for( beta = SMALL, i = 0; i <= SPIKETBLSIZE; i++ )
  145.       {   
  146.     if( i == SPIKETBLSIZE )
  147.         beta = LARGE;
  148.     for( alpha = SMALL, j = 0; j <= SPIKETBLSIZE; j++ )
  149.       {
  150.         if( j == SPIKETBLSIZE )
  151.         alpha = LARGE;
  152.         if( (alpha < .0399) || (alpha > .9601) )
  153.         step = .0001;
  154.         else if( (alpha < .0999) || (alpha > .9001) )
  155.         step = .001;
  156.         else
  157.         step = .01;
  158.  
  159.         if( (beta < .0399) || (beta > .9601) )
  160.         step = .0001;
  161.         else if( (beta < .0999) || (beta > .9001) )
  162.         step = (step < .0009) ? step : .001;
  163.  
  164.         nldltab[ i ][ j ] = nldl_rk4( alpha, beta, step );
  165.         nldhtab[ i ][ j ] = 1.0 - nldh_rk4( alpha, beta, step );
  166.         linear_spike( alpha, beta, &(delaytab[i][j]), &(linrtab[i][j]) );
  167.  
  168.         if( alpha == SMALL )
  169.         alpha = STEP;
  170.         else
  171.         alpha += STEP;
  172.       }
  173.     if( beta == SMALL )
  174.         beta = STEP;
  175.     else
  176.         beta += STEP;
  177.       }
  178.   }
  179.  
  180.  
  181. void rk4_error( which, alpha, beta, h )
  182.   char    *which;
  183.   double  alpha, beta, h;
  184.   {
  185.     fprintf( stderr, "RK4 error: %s: Didn't reach the peak\n", which );
  186.     fprintf( stderr, "alpha = %f beta = %f h = %f\n", alpha, beta, h );
  187.     exit( 1 );
  188.   }
  189.  
  190.     
  191. /* 
  192.  * 4th order Runge-Kutta method to solve 2-transistors-2-capacitors
  193.  * networks assuming quadratic transistor model.
  194.  * 
  195.  * 1) Driven path is ground.
  196.  * 2) Node 1 is discharged initially, and the ratio of its capacitance
  197.  *    to the total capacitance is equal to beta.
  198.  * 3) The ratio of resistance of the resistor closer to ground to the 
  199.  *    total resistrance is equal to alpha.
  200.  * 4) Step size is h.
  201.  * 5) Return the peak voltage observed at node 1.
  202.  *
  203.  * This routine is numerically stable when
  204.  *         i) h == .001; .04 < alpha < .96; .04 < beta < .96
  205.  *       ii) h == .01;  .1  < alpha < .9;  .1  < beta < .9
  206.  */
  207. double nldl_rk4( alpha, beta, h )
  208.   double alpha, beta, h;
  209.   {   
  210.     double        k11, k12, k21, k22, k31, k32, k41, k42;
  211.     double        v1old, v1new, v2old, v2new;
  212.     double        tmp1, tmp2;
  213.     register int  i, j;
  214.  
  215.     v1old = 0.0;               /* Initial Voltages */
  216.     v2old = 1.0;
  217.     j = (int) (1.0 / h);           /* Maximum number of iterations */
  218.  
  219.     for( i = 0; i < j; i++ )
  220.       {   
  221.     nldl_vector( alpha, beta, h, v1old, v2old, &k11, &k12 );
  222.     tmp1 = v1old + .5 * k11;
  223.     tmp2 = v2old + .5 * k12;
  224.     nldl_vector( alpha, beta, h, tmp1, tmp2, &k21, &k22 );
  225.     tmp1 = v1old + .5 * k21;
  226.     tmp2 = v2old + .5 * k22;
  227.     nldl_vector( alpha, beta, h, tmp1, tmp2, &k31, &k32 );
  228.     tmp1 = v1old + k31;
  229.     tmp2 = v2old + k32;
  230.     nldl_vector( alpha, beta, h, tmp1, tmp2, &k41, &k42 );
  231.     v1new = v1old + (k11 + 2.0 * k21 + 2.0 * k31 + k41) / 6.0;
  232.     v2new = v2old + (k12 + 2.0 * k22 + 2.0 * k32 + k42) / 6.0;
  233.     if (v1new < v1old)
  234.         return( v1old );        /* v1old is the peak */
  235.     v1old = v1new;
  236.     v2old = v2new;
  237.       }
  238.  
  239.     /* i >= j */
  240.     rk4_error( "nldl", alpha, beta, h );
  241.     return( 0.0 );
  242.   }
  243.  
  244.  
  245.         
  246. /* 
  247.  * This routine computes the parameter vector for Runge-Kutta method.
  248.  * Customized for 2-transistors-2-capacitors network driven by Gnd.
  249.  */
  250. void nldl_vector( alpha, beta, h, v1, v2, k1, k2 )
  251.   double alpha, beta, h, v1, v2, *k1, *k2;
  252.   {   
  253.     double  u1, u2;
  254.     
  255.     u1 = 2.0 * v1 - v1 * v1;
  256.     u2 = 2.0 * v2 - v2 * v2;
  257.  
  258.     *k1 = h * (alpha * u2 - u1) / ( alpha * beta * (1.0 - alpha) );
  259.     *k2 = h * (u1 - u2) / ((1.0 - alpha) * (1.0 - beta));
  260.   }
  261.  
  262.  
  263. /* 
  264.  * 4th order Runge-Kutta method to solve 2-transistors-2-capacitors
  265.  * networks assuming quadratic transistor model.
  266.  * 
  267.  * 1) Driven path is Vdd.
  268.  * 2) Node 1 is charged high initially, and the ratio of its capacitance
  269.  *    to the total capacitance is equal to beta.
  270.  * 3) The ratio of resistance of the resistor closer to driver to the 
  271.  *    total resistrance is equal to alpha.
  272.  * 4) Step size is h.
  273.  * 5) Return the peak voltage observed at node 1.
  274.  *
  275.  * This routine is numerically stable when
  276.  *         i) h == .001; .04 < alpha < .96; .04 < beta < .96
  277.  *       ii) h == .01;  .1  < alpha < .9;  .1  < beta < .9
  278.  */
  279. double nldh_rk4( alpha, beta, h )
  280.   double alpha, beta, h;
  281.   {   
  282.     double        k11, k12, k21, k22, k31, k32, k41, k42;
  283.     double        v1old, v1new, v2old, v2new;
  284.     double        tmp1, tmp2;
  285.     register int  i, j;
  286.  
  287.     v1old = 1.0;               /* Initial Voltages */
  288.     v2old = 0.0;
  289.     j = (int) (1.0 / h);           /* Maximum number of iterations */
  290.  
  291.     for( i = 0; i < j; i ++ )
  292.       {   
  293.     nldh_vector( alpha, beta, h, v1old, v2old, &k11, &k12 );
  294.     tmp1 = v1old + .5 * k11;
  295.     tmp2 = v2old + .5 * k12;
  296.     nldh_vector( alpha, beta, h, tmp1, tmp2, &k21, &k22 );
  297.     tmp1 = v1old + .5 * k21;
  298.     tmp2 = v2old + .5 * k22;
  299.     nldh_vector( alpha, beta, h, tmp1, tmp2, &k31, &k32 );
  300.     tmp1 = v1old + k31;
  301.     tmp2 = v2old + k32;
  302.     nldh_vector( alpha, beta, h, tmp1, tmp2, &k41, &k42 );
  303.     v1new = v1old + (k11 + 2.0 * k21 + 2.0 * k31 + k41) / 6.0;
  304.     v2new = v2old + (k12 + 2.0 * k22 + 2.0 * k32 + k42) / 6.0;
  305.     if( v1new > v1old )
  306.         return( v1old );    /* v1old is the peak */
  307.     v1old = v1new;
  308.     v2old = v2new;
  309.       }
  310.  
  311.     /* i >= j */
  312.     rk4_error( "nldh", alpha, beta, h );
  313.     return( 0.0 );
  314.   }
  315.  
  316.  
  317.         
  318. /* 
  319.  * This routine computes the parameter vector for Runge-Kutta method.
  320.  * Customized for 2-transistors-2-capacitors network driven by Vdd.
  321.  */
  322. void nldh_vector( alpha, beta, h, v1, v2, k1, k2 )
  323.   double alpha, beta, h, v1, v2, *k1, *k2;
  324.   {   
  325.     double  u1, u2;
  326.     
  327.     u1 = 1.0 - 2.0 * v1 + v1 * v1;
  328.     u2 = 1.0 - 2.0 * v2 + v2 * v2;
  329.  
  330.     *k1 = -h * (alpha * u2 - u1) / ( alpha * beta * (1.0 - alpha) );
  331.     *k2 = -h * (u1 - u2) / ((1.0 - alpha) * (1.0 - beta));
  332.   }
  333.  
  334.  
  335. /*
  336.  * Compute spike fluctuation and delay using an rc linear model.
  337.  * Use equations for driven by Gnd case
  338.  */
  339. void linear_spike( alpha, beta, delay, peak )
  340.   double  alpha, beta, *delay, *peak;
  341.   {
  342.     double  N, b, a, x, tmp;
  343.  
  344.     tmp = alpha * beta + 1.0 - beta;
  345.     N = alpha * beta * (1.0 - alpha) * (1.0 - beta) / (tmp * tmp);
  346.     a = sqrt( 1.0 - 4.0 * N );
  347.     x = (1.0 - a) / (1.0 + a);
  348.     b = (1.0 + x) * exp( x * log( x ) / (1.0 - x) );
  349.     *peak = b * alpha * (1.0 - beta) / tmp;
  350.  
  351.     x = (1.0 + a) / (1.0 - a);
  352.     b = log( x ) / a;
  353.     *delay = b * beta * (1.0 - alpha) / alpha;
  354.   }
  355.